package com.fenxiangtech.mall.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import tech.ideashare.se.is_annotation.IS_Description;
import tech.ideashare.se.model.IS_JavaDoc;
import tech.ideashare.se.model.IS_WebProjectConfig;
import tech.ideashare.se.utils.IS_HttpUtils;
import tech.ideashare.se.utils.IS_StringUtils;
import tech.ideashare.se.utils.LX_HttpUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.util.*;

/**
 *
 * @Author lixiang
 * @CreateTime 11/04/2018
 **/
public class Mall_GenDocUtils {


   public static void  generateDocToMarkDownFile(Class clazz){
       List<IS_JavaDoc> javaDocs = generateDocByReflect(clazz);
     //  formatJavaDocToMarkDown(javaDocs,clazz.getSimpleName());
   }

    /**
     * 用反射去获取接口信息，注释可以考虑用String工具类里面的方法去截取
     * @param clazz
     * @return
     */
    public static List<IS_JavaDoc> generateDocByReflect(Class clazz){

        List<IS_JavaDoc> javaDocList = new ArrayList<>();

        String rootUrl = "";
        for (Annotation annotation : clazz.getAnnotations()) {
            String annotationName = annotation.annotationType().getSimpleName();
            if(annotationName.equals("RequestMapping")){
                String totalInfo  = annotation.toString();
                String sub  = IS_StringUtils.getSubstringBetweenFL(totalInfo,"value",",");
                String value = IS_StringUtils.getSubstringBetweenFL(sub,"\"","\"");
                rootUrl = value;
            }

        }


        for (Method method : clazz.getDeclaredMethods()) {
            IS_JavaDoc javaDoc = new IS_JavaDoc();
            Map<String,String> paramJsonObject = new HashMap<>();
            JSONObject returnJsonObject = new JSONObject();
            //获取方法名
            javaDoc.setApiMethodName(method.getName());
            String methodUrl;
            //获取方法上的注解
            for (Annotation annotation : method.getAnnotations()) {
                String annotationName = annotation.annotationType().getSimpleName();
                if(annotationName.equals("RequestMapping")||annotationName.equals("GetMapping")||annotationName.equals("PostMapping")){
                    String value = "";
                    try {
                        Method me = annotation.annotationType().getMethod("value");
                        value  = ((String[]) me.invoke(annotation))[0];
                        System.out.println(value);
                    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }

//                    String totalInfo  = annotation.toString();
//                    String sub  =IS_StringUtils.getSubstringBetweenFL(totalInfo,"value",",");
//                    String value = IS_StringUtils.getSubstringBetweenFL(sub,"[","]");
                    methodUrl=rootUrl+value;
                    javaDoc.setApiUrl(methodUrl);
                    String type  = annotationName.equals("PostMapping")?"POST":"GET";
                    javaDoc.setApiType(type);
                }
                if(annotationName.equals("IS_Description")){
                    IS_Description description = (IS_Description) annotation;
                    javaDoc.setApiMethodDesc(description.value());
                }
            }
            //获取方法的入参
            for (Parameter parameter : method.getParameters()) {
                    //参数名
                    String paramName = parameter.getName();
                    Class paramClass = parameter.getType();
                    String classType = judgeBaseClass(paramClass);
                    //对类进行判断，如果是基本类型，则返回参数名
                    //如果是其他类型，则通过反射获取里面的变量名或者直接实例化然后json输出
                    if(classType.equals("base")){
                        paramJsonObject.put(paramName,"null");
                    }else if(classType.equals("model")){
                        paramJsonObject.put(paramName,objToJson(paramClass));
                    }
            }

            //返回值获取的先注掉
//            //获取方法的回参
//            Type type =  method.getGenericReturnType();
//            //获取泛型
//            if(type instanceof ParameterizedType){
//                ParameterizedType parameterizedType = (ParameterizedType) type;
//                Type argument = parameterizedType.getActualTypeArguments()[0];
//                if(argument instanceof ParameterizedType){
//                    //两层嵌套,最多也就支持两层，后面可能改下代码支持多层，现在先简单了写
//                    ParameterizedType subType = (ParameterizedType) argument;
//                    Type subArgument = subType.getActualTypeArguments()[0];
//                    Class<?> cc = (Class<?>) subArgument;
//                    String s = judgeBaseClass(cc);
//                    if (s.equals("base")){
//                        returnJsonObject.put(cc.getSimpleName(),"null");
//                    }else if (s.equals("model")){
//                        returnJsonObject.put(cc.getSimpleName(),objToJson(cc));
//                    }
//                }else {
//                    Class<?> cc = (Class<?>) argument;
//                    String s = judgeBaseClass(cc);
//                    if (s.equals("base")){
//                        returnJsonObject.put(cc.getSimpleName(),"null");
//                    }else if (s.equals("model")){
//                        returnJsonObject.put(cc.getSimpleName(),objToJson(cc));
//                    }
//                }
//            }else {
//                //最外层就是实体类
//                Class<?> cc = (Class<?>) type;
//                String s = judgeBaseClass(cc);
//                if (s.equals("base")){
//                    returnJsonObject.put(cc.getSimpleName(),"null");
//                }else if (s.equals("model")){
//                    returnJsonObject.put(cc.getSimpleName(),objToJson(cc));
//                }
//            }
//            System.out.println(JSON.toJSONString(type));
//            Class<?> returnType = method.getReturnType();
//            String s = judgeBaseClass(returnType);
//            if (s.equals("base")){
//                returnJsonObject.put(returnType.getSimpleName(),"null");
//            }else if (s.equals("model")){
//                returnJsonObject.put(returnType.getSimpleName(),objToJson(returnType));
//            }

            javaDoc.setRequestParamMap(paramJsonObject);
         //   javaDoc.setResponseJson(returnJsonObject.toJSONString());
            javaDocList.add(javaDoc);
        }

//        System.out.println(JSON.toJSONString(javaDocList));

        return  javaDocList;
    }

    public static void main(String[] args) {

        judgeBaseClass(int.class);
    }

    /**
     * 判断是否是基础类
     * @param clazz
     * @return
     */
    public  static  String judgeBaseClass(Class clazz){
        if(clazz.equals(String.class)
                ||clazz.equals(Date.class)
                ||clazz.equals(Long.class)
                ||clazz.equals(Boolean.class)
                ||clazz.equals(BigDecimal.class)
                ||clazz.equals(Integer.class)
                ||clazz.equals(Double.class)
                ||clazz.equals(int.class)
                ||clazz.equals(boolean.class)
                ||clazz.equals(long.class)
                ||clazz.equals(double.class)){
            return "base";
        }else if(clazz.equals(List.class)){
            return "list";
        }else {
            return "model";
        }
    }

    /**
     * 把一个类clazz 输出成json ，支持二级实例对象
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
    public static String objToJson(Class clazz){
        Object pObj = null;
        try {
            //先把上级实体给实例化
            pObj = clazz.getDeclaredConstructor().newInstance();
            for (Field field : clazz.getDeclaredFields()) {
                Class clazzType  = field.getType();
                String clazzTypeStr = judgeBaseClass(clazzType);
                if(clazzTypeStr.equals("model")){
                    //如果是其他类形的话，通过反射把值给set进去
                    field.setAccessible(true);
                    Object subObj = clazzType.getDeclaredConstructor().newInstance();
                    field.set(pObj,subObj);
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        String objStr  = JSON.toJSONString(pObj,SerializerFeature.WriteMapNullValue);

        return objStr;
    }

//    public static void formatJavaDocToMarkDown(List<IS_JavaDoc> docList,String name) {
//
//            StringBuilder stringBuilder = new StringBuilder("# "+name+"\n");
//            for (IS_JavaDoc doc : docList) {
//                stringBuilder.append("## "+doc.getApiName()+"\n");
//                stringBuilder.append("```json\n");
//                stringBuilder.append("{\n");
//                stringBuilder.append("\t\"url\":\""+doc.getApiUrl()+"\",\n");
//                stringBuilder.append("\t\"method\":\""+doc.getApiMethodName()+"\",\n");
//                stringBuilder.append("\t\"desc\":\""+doc.getApiMethodDesc()+"\"\n");
//                stringBuilder.append("}\n```\n");
//
//                stringBuilder.append("### 请求入参\n");
//                stringBuilder.append("```json\n{\n");
//
//                stringBuilder.append(doc.getRequestParamJson().replaceAll(",",",\n"));
//
//                stringBuilder.append("\n}\n```\n");
//
//                stringBuilder.append("### 请求回参\n");
//                stringBuilder.append("```json\n{\n");
//                stringBuilder.append(doc.getResponseJson().replaceAll(",","\n"));
//
//                stringBuilder.append("\n}\n```\n");
//            }
//            System.out.println(stringBuilder.toString());
//
//        FileWriter writer = null;
//        try {
//            writer = new FileWriter(name+".md");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        BufferedWriter out = new BufferedWriter(writer);
//        try {
//            out.write(stringBuilder.toString());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        try {
//            out.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//    }

    public static void getResponse(List<IS_JavaDoc> javaDocList, IS_WebProjectConfig config){
        for (IS_JavaDoc is_javaDoc : javaDocList) {
            //请求链接
            String url  = config.getRootWebUrl()+is_javaDoc.getApiUrl();
            var object =  is_javaDoc.getRequestParamMap();
            HashMap<String,String> hashMap = new HashMap<>();
            object.forEach((s, o) -> hashMap.put(s,(String) o));

            if(is_javaDoc.getApiType().equals("GET")){
                String returnStr = LX_HttpUtils.getAsString(url, hashMap);
                Map<String, Object> responseParam = JSONObject.parseObject(returnStr, new TypeReference<>() {
                });
                is_javaDoc.setResponseParamMap(responseParam);

            }else {
                String returnStr  = IS_HttpUtils.postAsString(url,hashMap);
                Map<String, Object> responseParam = JSONObject.parseObject(returnStr, new TypeReference<>() {
                });
                is_javaDoc.setResponseParamMap(responseParam);
            }


        }
    }
    public static void getResponse(JSONObject is_javaDoc, IS_WebProjectConfig config){
        //请求链接
        String url  = config.getRootWebUrl()+is_javaDoc.getString("apiUrl");
        JSONObject object = (JSONObject) is_javaDoc.get("requestParamMap");
        HashMap<String,String> hashMap = new HashMap<>();
        object.forEach((s, o) -> hashMap.put(s,(String) o));

        if(is_javaDoc.getString("apiType").equals("GET")){
            String returnStr = LX_HttpUtils.getAsString(url, hashMap);
            Map<String, Object> postParam = JSONObject.parseObject(returnStr, new TypeReference<>() {
            });
            JSONObject object1 = JSONObject.parseObject(returnStr,Feature.InitStringFieldAsEmpty);
            System.out.println(object1);
        }else {
            JSONObject json = IS_HttpUtils.postAsJson(url,hashMap);
            System.out.println(json);
        }
    }

    public static void getResponse(String javaDocJSON, IS_WebProjectConfig config){
        List<IS_JavaDoc> is_javaDocs = JSONArray.parseArray(javaDocJSON, IS_JavaDoc.class);
        getResponse(is_javaDocs,config);
    }

}
